/*
        Firesoft 
        
    Copyright (C) 2010, Arttu Viljakainen 
    Published under GNU General Public License V3 
    (see http://www.gnu.org/licenses/licenses.html)
    
    This file is part of Firesoft.

    Firesoft is free software: 
    you can redistribute it and/or modify it under the terms of the GNU General 
    Public License as published by the Free Software Foundation, 
    either version 3 of the License, or (at your option) any later version.

    Firesoft is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
    Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tool for Path Finding Algorithm Testing. If not, see         
    <http://www.gnu.org/licenses/>.
 */
package softstarter.gui;

/**
 * http://melloware.com/products/jintellitype/quick-start.html
 * http://java.sun.com/developer/technicalArticles/J2SE/Desktop/javase6/systemtray/
 */
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.dnd.DropTarget;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;
import javax.swing.UnsupportedLookAndFeelException;

import softstarter.functionality.ActionsController;
import softstarter.functionality.ControllerInterface;
import softstarter.functionality.FileCentre;
import softstarter.functionality.FireActionsListener;
import softstarter.functionality.MinimizeMaximizeListener;
import softstarter.functionality.RunnableItem;
import softstarter.functionality.TrayMouseListener;
import softstarter.gui.settingsgui.FilesAndButtons;

import com.melloware.jintellitype.JIntellitype;



public class SoftStarter extends JFrame implements DropTargetListener {

	private JPanel masterContainer;
	private JComboBox commandLine;
	private JButton goButton;
	private DropTarget dropTarget;
	
	private JButton showFilelistButton;
	private JButton hideFIlelistButton;
	private FireActionsListener fireActionListener;
	private ControllerInterface actionController;
	private FilesAndButtons filesAndButtons;
	private FileCentre fileCentre;
	
	protected TrayIcon trayIcon;
	
	private SoftStarter() {
		
		this.setTitle("Firesoft");
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	    this.setUndecorated(true);
	    
		setNimbusLookAndFeel();
		buildGUI();
		checkIfOperationsAreSupported();
		checkWhichVersionOfWindows();
		registerWindowsHotkey();
		createSystemTrayFunctionality();
		
	}
	
	private void checkIfOperationsAreSupported() {
		System.out.println(System.getProperty("os.arch") + " " + System.getProperty("os.version"));
		if(!Desktop.isDesktopSupported() || !SystemTray.isSupported()) {
			JOptionPane.showMessageDialog(this,
				    "Your operating environment doesn't support the operations of this program.",
				    "Sorry",
				    JOptionPane.ERROR_MESSAGE);
			System.exit(0);
		}
	}
	
	private void checkWhichVersionOfWindows() {
		if(System.getProperty("os.arch").contains("64"))
			JIntellitype.setLibraryLocation("resources/JIntellitype64.dll");
		else
			JIntellitype.setLibraryLocation("resources/JIntellitype.dll");
	}
	
	private void buildGUI() {
		
	    dropTarget = new DropTarget(this, this);

		fileCentre = new FileCentre();
		this.filesAndButtons = new FilesAndButtons(fileCentre, this);
		
		GridBagLayout layout = new GridBagLayout();
		GridBagConstraints constr = new GridBagConstraints();
		masterContainer = new JPanel(layout);

		actionController = ActionsController.getInstance(fileCentre);
		fireActionListener = new FireActionsListener(actionController, this);
		
		commandLine = new JComboBox();
		commandLine.setEditable(true);
		System.out.println(commandLine.getSize());
		commandLine.getEditor().getEditorComponent().addKeyListener(fireActionListener);
	
		actionController.setHost(this);

		goButton = new JButton("Go");
		goButton.addActionListener(fireActionListener);
		
		showFilelistButton = new JButton("Show files");
		showFilelistButton.addActionListener(fireActionListener);
		
		hideFIlelistButton = new JButton("Hide files");
		hideFIlelistButton.addActionListener(fireActionListener);
		
		constr.gridx = 0; constr.gridy = 0;
		masterContainer.add(commandLine, constr);
		constr.gridx = 1; constr.gridy = 0;
		masterContainer.add(goButton, constr);
		constr.gridx = 2; constr.gridy = 0;
		masterContainer.add(showFilelistButton, constr);
		
		this.add(masterContainer);
		this.addWindowStateListener(new MinimizeMaximizeListener(this));
		
		this.commandLine.setPreferredSize(new Dimension(300, 20));
		this.setAlwaysOnTop(true);
		this.pack();
		this.setVisible(true);
	}
	
	private void setNimbusLookAndFeel() {
		try {
		    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
		        if ("Nimbus".equals(info.getName())) {
		            UIManager.setLookAndFeel(info.getClassName());
		            break;
		        }
		    }
		} catch (UnsupportedLookAndFeelException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} 
	}
	
	public void populateCommandLineAndShowPopup(List<RunnableItem> topHits) {
		
		String firstElement = commandLine.getEditor().getItem().toString();
		commandLine.removeAllItems();
		
		for(RunnableItem file: topHits) {
			System.out.println("--->" + file.getName());
			commandLine.addItem(file);
		}
		commandLine.getEditor().setItem(firstElement);

		commandLine.revalidate();
		
		commandLine.showPopup();
		
		pack();
	}
		
	private void registerWindowsHotkey() {
		        
        JIntellitype.getInstance().registerHotKey(1,JIntellitype.MOD_WIN, (int)'S' );

        JIntellitype.getInstance().addHotKeyListener(fireActionListener);
	
	}
		
	private void createSystemTrayFunctionality() {
		
		if (SystemTray.isSupported()) {

		    SystemTray tray = SystemTray.getSystemTray();
		    Image image = Toolkit.getDefaultToolkit().getImage("./resources/tray.gif");
		    		            
		    PopupMenu popup = new PopupMenu();
		    MenuItem exitMenuItem = new MenuItem("Exit");
		    exitMenuItem.addActionListener(fireActionListener);
		    popup.add(exitMenuItem);

		    MenuItem settingsMenuItem = new MenuItem("Settings");
		    settingsMenuItem.addActionListener(fireActionListener);
		    popup.add(settingsMenuItem);

		    trayIcon = new TrayIcon(image, "Firesoft", popup);
		            
		    trayIcon.setImageAutoSize(true);
		    trayIcon.addMouseListener(new TrayMouseListener(this));

		    try {
		        tray.add(trayIcon);
		    } catch (AWTException e) {
		        System.err.println("Failed to add tray icon.");
		    }

		} 
		
	}
	
	public JComboBox getCommandLine() {
		return commandLine;
	}
	
	public void hideFileList() {
		masterContainer.remove(filesAndButtons);
		masterContainer.remove(hideFIlelistButton);
		GridBagConstraints constr = new GridBagConstraints();
		constr.gridx = 2; constr.gridy = 0;
		masterContainer.add(showFilelistButton, constr);

		pack();
		this.setVisible(true);
	}
	
	public void showFileList() {
		updateFileList();
		GridBagConstraints constr = new GridBagConstraints();
		constr.gridx = 0; constr.gridy = 1;
		masterContainer.add(filesAndButtons, constr);
		masterContainer.remove(showFilelistButton);
		constr.gridx = 2; constr.gridy = 0;
		masterContainer.add(hideFIlelistButton, constr);

		pack();
		this.setVisible(true);
	}
	
	public void updateFileList() {
		filesAndButtons.buildListWithFilesAndRemoveButtons();
		pack();
	}

	public static void main(String[] args) {
		SwingUtilities.invokeLater(new Runnable() {
		    public void run() {
				new SoftStarter();
		    }
		});
	}

	@Override
	public void dragEnter(DropTargetDragEvent dtde) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void dragExit(DropTargetEvent dte) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void dragOver(DropTargetDragEvent dtde) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void drop(DropTargetDropEvent dropEvent) {
        final List result = new ArrayList();
        int action = dropEvent.getDropAction();
        dropEvent.acceptDrop(action);
        try {
            Transferable data = dropEvent.getTransferable();
            DataFlavor flavors[] = data.getTransferDataFlavors();
            if (data.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                List<File> files = (List<File>) data.getTransferData(
                    DataFlavor.javaFileListFlavor);
                fileCentre.addJavaFiles(files);
                updateFileList();
                	
            }
        } catch (UnsupportedFlavorException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            dropEvent.dropComplete(true);
            repaint();
        }		
	}

	@Override
	public void dropActionChanged(DropTargetDragEvent dtde) {
		// TODO Auto-generated method stub
		
	}
	
}
